package cn.xinfei.xdecision.engine.runner.executor;

import cn.xinfei.xdecision.constant.EngineResultEnum;
import cn.xinfei.xdecision.constant.GlobalConstant;
import cn.xinfei.xdecision.engine.runner.context.PipelineContextHolder;
import cn.xinfei.xdecision.engine.runner.context.PipelineMetaInfoContext;
import cn.xinfei.xdecision.engine.runner.context.XDecisionContext;
import cn.xinfei.xdecision.engine.runner.executor.model.StateTransmitModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

import static cn.xinfei.xdecision.constant.EngineResultEnum.EXCEPTION;

@Slf4j
public class DecisionFlowPipeline extends DecisionFlow {


    /**
     * 决策流执行
     *
     * @return
     */
    public static StateTransmitModel fire() {
        StateTransmitModel stateTransmitModel = XDecisionContext.getContext().getStateContext();
        NodeHandler current = getFirst();
        if (null == current || null == current.getNextNodes()) {
            log.info("节点流没有起始节点，或者没有next node，node={}", current);
            return stateTransmitModel.setEngineResultEnum(EngineResultEnum.NO_EXISTS);
        }
        try {
            stateTransmitModel = run(current);
            //同步的终止逻辑
            EngineResultEnum engineResultEnum = stateTransmitModel.getEngineResultEnum();
            if (PipelineContextHolder.getSync().equals("SYNC") &&
                    (engineResultEnum.getResult().equals(EngineResultEnum.PROCESSING.getResult())
                            || engineResultEnum.getResult().equals(EngineResultEnum.PENDING.getResult()))) {
                log.warn("同步场景,进入[{}]非终止状态,统一改为异常终止", engineResultEnum);
                stateTransmitModel.setEngineResultEnum(EXCEPTION);
            }

            blow(stateTransmitModel);
//            log.info("执行节点流结束，stateTransmitModel={}", stateTransmitModel);
            return stateTransmitModel;
        } catch (Exception e) {
            log.error("执行节点流异常，node={}，error={}", current, e.getMessage(), e);
            return stateTransmitModel.setEngineResultEnum(EngineResultEnum.EXCEPTION_END);
        }
    }

    /**
     * 重入执行
     *
     * @param nodeCode
     * @return
     */
    public static StateTransmitModel reentry(String nodeCode) {
        XDecisionContext context = XDecisionContext.getContext();
        PipelineMetaInfoContext pipelineMetaInfoContext = context.getPipelineMetaInfoContext();
        StateTransmitModel stateTransmitModel = XDecisionContext.getContext().getStateContext();
        NodeHandler current = null;
        if (StringUtils.isNotEmpty(nodeCode)) {
            current = pipelineMetaInfoContext.get(nodeCode);
        }
        if (StringUtils.isEmpty(nodeCode) || null == current) {
            log.error("context里不存在 nodeCode={}", nodeCode);
            return stateTransmitModel.setEngineResultEnum(EngineResultEnum.NO_EXISTS);
        }

        StateTransmitModel transmitModel = run(current);
        blow(transmitModel);
        return transmitModel;
    }

    /**
     * 执行一个节点
     *
     * @param curr
     * @return
     */
    public static StateTransmitModel shoot(NodeHandler curr) {
        StateTransmitModel transmitModel = run(curr);
        blow(transmitModel);
        return transmitModel;
    }

    /**
     * 单次执行，执行某个节点，或者某个组件实例
     *
     * @param examHandler
     * @return
     */
    public static StateTransmitModel launch(AbsNodeHandler examHandler) {
        String nodeCode = examHandler.getCode();
        MDC.put(GlobalConstant.NID, nodeCode);
        log.info("node start launch");
        StateTransmitModel handler = examHandler.handler();
        log.info("node end，transmitModel={}", nodeCode, handler);
        return handler;
    }

    /**
     * 执行完决策流，将决策结果统一存储到上下文中
     *
     * @param transmitModel
     */
    private static void blow(StateTransmitModel transmitModel) {
        EngineResultEnum engineResultEnum = transmitModel.getEngineResultEnum();
        PipelineContextHolder.setEngineResult(engineResultEnum);
        PipelineContextHolder.setOutput(PipelineContextHolder.getOut());
    }


}
